package com.alks.function.service.serviceImpl.finance.statement;


import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import com.alks.common.aop.RedisLock;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.utils.DateUtils;
import com.alks.common.utils.beanutils.ObjectUtils;
import com.alks.common.utils.excelUtils.ExcelPoiUtils;
import com.alks.common.utils.excelUtils.ExcelUtils;
import com.alks.entity.data.entity.DhDeptProdStatusD;
import com.alks.entity.data.entity.ProdDept;
import com.alks.entity.data.page.PageParam;
import com.alks.entity.data.page.PageRecord;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.data.dto.biocontrol.factoryQuery.DailyReportDetailDto;
import com.alks.function.data.dto.finance.statement.DhDeptProdStatusMHorizontalDto;
import com.alks.function.mapper.biocontrol.factoryQuery.PcCuttingDailyReportMapper;
import com.alks.function.mapper.biocontrol.factoryQuery.PcLastCollectDetailMapper;
import com.alks.function.mapper.finance.statement.GenerateProdReportMapper;
import com.alks.function.mapper.finance.statement.ProdDeptMapper;
import com.alks.function.mapper.pcfactoryquery.FT_QR_PcStitchDetailAttachMapper;
import com.alks.function.service.biocontrol.factoryQuery.IStkAccService;
import com.alks.function.service.finance.statement.GenerateProdReportService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jodd.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class GenerateProdReportServiceImpl implements GenerateProdReportService {

    @Autowired
    private GenerateProdReportMapper generateProdReportMapper;

    @Autowired
    private ProdDeptMapper deptMapper;

    @Autowired
    private IStkAccService stkAccService;

    private final FT_QR_PcStitchDetailAttachMapper stitchMapper;
    private final PcCuttingDailyReportMapper cutMapper;
    private final PcLastCollectDetailMapper lastMapper;


    /**
     * 获取指令产量明细
     * @param year
     * @return
     */
    @Override
    public ResponseInfo getMonthProd(String year) {
        String companyId = UserIdThread.get().getCompanyId();
        //表头
        List<String> headList = generateProdReportMapper.getMonthHeadList(year);

        //表中间的数据
        //分情况处理，分2025年以前，以及2025年以及以后
        // 将年份字符串转换为整数

        int yearInt = Integer.parseInt(year);

        List<DhDeptProdStatusMHorizontalDto> bodyList = new ArrayList<>();
        if(yearInt >= 2025){
            bodyList = generateProdReportMapper.getDeptYearAndMonthProd(year,companyId);
        }else{
            bodyList = generateProdReportMapper.getDeptYearAndMonthProd1(year,companyId);
        }

        if(ObjectUtils.isNotEmpty(bodyList)){
            //计算年产量合计
            for (DhDeptProdStatusMHorizontalDto dto : bodyList) {
                BigDecimal sum = BigDecimal.ZERO;
                sum = sum.add(dto.getProdQty1() != null ? dto.getProdQty1() : BigDecimal.ZERO)
                        .add(dto.getProdQty2() != null ? dto.getProdQty2() : BigDecimal.ZERO)
                        .add(dto.getProdQty3() != null ? dto.getProdQty3() : BigDecimal.ZERO)
                        .add(dto.getProdQty4() != null ? dto.getProdQty4() : BigDecimal.ZERO)
                        .add(dto.getProdQty5() != null ? dto.getProdQty5() : BigDecimal.ZERO)
                        .add(dto.getProdQty6() != null ? dto.getProdQty6() : BigDecimal.ZERO)
                        .add(dto.getProdQty7() != null ? dto.getProdQty7() : BigDecimal.ZERO)
                        .add(dto.getProdQty8() != null ? dto.getProdQty8() : BigDecimal.ZERO)
                        .add(dto.getProdQty9() != null ? dto.getProdQty9() : BigDecimal.ZERO)
                        .add(dto.getProdQty10() != null ? dto.getProdQty10() : BigDecimal.ZERO)
                        .add(dto.getProdQty11() != null ? dto.getProdQty11() : BigDecimal.ZERO)
                        .add(dto.getProdQty12() != null ? dto.getProdQty12() : BigDecimal.ZERO);
                dto.setProdQtyCount(sum);
            }
        }


        HashMap map = new HashMap<>();
        map.put("headList",headList);
        map.put("bodyList",bodyList);
        return ResponseInfo.ok(map);
    }

    /**
     * 导出
     * @param year
     * @param response
     */
    @Override
    public void exportMonthProd(String year, HttpServletResponse response) {
        String companyId = UserIdThread.get().getCompanyId();
        //表头
        List<String> headList = generateProdReportMapper.getMonthHeadList(year);

        //表中间的数据
        //分情况处理，分2025年以前，以及2025年以及以后
        // 将年份字符串转换为整数

        int yearInt = Integer.parseInt(year);

        List<DhDeptProdStatusMHorizontalDto> bodyList = new ArrayList<>();
        if(yearInt >= 2025){
            bodyList = generateProdReportMapper.getDeptYearAndMonthProd(year,companyId);
        }else{
            bodyList = generateProdReportMapper.getDeptYearAndMonthProd1(year,companyId);
        }

        if(ObjectUtils.isNotEmpty(bodyList)){
            //计算年产量合计
            for (DhDeptProdStatusMHorizontalDto dto : bodyList) {
                BigDecimal sum = BigDecimal.ZERO;
                sum = sum.add(dto.getProdQty1() != null ? dto.getProdQty1() : BigDecimal.ZERO)
                        .add(dto.getProdQty2() != null ? dto.getProdQty2() : BigDecimal.ZERO)
                        .add(dto.getProdQty3() != null ? dto.getProdQty3() : BigDecimal.ZERO)
                        .add(dto.getProdQty4() != null ? dto.getProdQty4() : BigDecimal.ZERO)
                        .add(dto.getProdQty5() != null ? dto.getProdQty5() : BigDecimal.ZERO)
                        .add(dto.getProdQty6() != null ? dto.getProdQty6() : BigDecimal.ZERO)
                        .add(dto.getProdQty7() != null ? dto.getProdQty7() : BigDecimal.ZERO)
                        .add(dto.getProdQty8() != null ? dto.getProdQty8() : BigDecimal.ZERO)
                        .add(dto.getProdQty9() != null ? dto.getProdQty9() : BigDecimal.ZERO)
                        .add(dto.getProdQty10() != null ? dto.getProdQty10() : BigDecimal.ZERO)
                        .add(dto.getProdQty11() != null ? dto.getProdQty11() : BigDecimal.ZERO)
                        .add(dto.getProdQty12() != null ? dto.getProdQty12() : BigDecimal.ZERO);
                dto.setProdQtyCount(sum);
            }
        }

        HashMap map = new HashMap<>();
        map.put("headList",headList);
        map.put("bodyList",bodyList);

        //开启横向遍历
        TemplateExportParams templateParams = new TemplateExportParams("templates/月度产量报表.xlsx", true);
        templateParams.setColForEach(true);
        String fileName = year + "年月度产量报表_" + DateUtils.dateTimeNow() + ".xlsx";
        try {
            ExcelUtils.setResponseZF(response, fileName);
            ExcelPoiUtils.writeExcelList1(response, map, templateParams);
        } catch (Exception e) {
            log.error("月度产量报表导出失败, 错误信息: {}", e.getMessage());
            throw new ServiceErrorException("导出失败");
        }

    }

    @Override
    public PageRecord<List<String>> getDailyProd(PageParam request, LocalDateTime startDate, LocalDateTime endDate) {
        String companyId = UserIdThread.get().getCompanyId();
        List<String> headList = new ArrayList<>();
        List<LocalDateTime> dateList = new ArrayList<>();
        int total = request.getPageNum() * request.getPageSize();
        PageRecord<List<String>> pageRecord = new PageRecord<>();
        LocalDateTime startDateReq = startDate;
        LocalDateTime endDateReq = endDate;
        /*分页后日期处理*/
        if (!request.getPageSize().equals(-1)&& !request.getPageNum().equals(-1)) {
            long daysBetween = ChronoUnit.DAYS.between(startDate, endDate);
            pageRecord.setTotal(daysBetween);
            boolean before = startDate.plusDays(total).isBefore(endDate);
            endDate = before ? startDate.plusDays(total):endDate;
            startDate = startDate.plusDays(total - request.getPageSize());
        }
        /*获取表头数据*/
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (int i = 0;!startDate.plusDays(i).isAfter(endDate);i++) {
            headList.add(startDate.plusDays(i).format(formatter));
            dateList.add(startDate.plusDays(i));
        }
        /*获取部门数据*/
        List<String> deptList = deptMapper.dailyDept(companyId);
        /*获取实体数据*/
        List<DhDeptProdStatusD> prodList = generateProdReportMapper.getDailyProd(startDate,endDate);
        /*数据平铺*/
        List<List<String>> bodyList = new ArrayList<>();
        //获取 部门_日期 与 产量的键值对方便获取数据
        Map<String, BigDecimal> qtyMap = prodList.stream()
                .filter(Objects::nonNull)
                .filter(a->a.getProdDate()!=null&& StringUtil.isNotBlank(a.getDeptName()))
                .collect(Collectors.toMap(a->a.getDeptName()+ "_" + a.getProdDate().format(formatter),
                        a->a.getProdQty()==null?BigDecimal.ZERO:a.getProdQty(),
                        BigDecimal::add));
        //获取 部门 与 产量合计的键值对方便获取数据
        List<DhDeptProdStatusD> prodList2 = generateProdReportMapper.getDailyProd(startDateReq,endDateReq);
        Map<String, BigDecimal> sumMap = prodList2.stream()
                .filter(Objects::nonNull)
                .filter(a->a.getProdDate()!=null&& StringUtil.isNotBlank(a.getDeptName()))
                .collect(Collectors.toMap(DhDeptProdStatusD::getDeptName,
                        a->a.getProdQty()==null?BigDecimal.ZERO:a.getProdQty(),
                        BigDecimal::add));
        for (String dept : deptList) {
            List<String> body = new ArrayList<>();
            /*处理部门名称和部门类别*/
            String[] split = dept.split("_");
            String prodStep = split[0];
            String deptName = split[1];
            body.add(prodStep);
            body.add(deptName);
            body.add(sumMap.get(deptName)==null?"0":sumMap.get(deptName).toString());

            for (LocalDateTime date : dateList) {
                /*处理产量数据，没有则补0*/
                String key = deptName + "_" + date.format(formatter);
                String prodQty = qtyMap.get(key)==null?"0":qtyMap.get(key).toString();
                body.add(prodQty);
            }
            bodyList.add(body);
        }
        pageRecord.setList(bodyList);
        pageRecord.setOtherList(headList);
        return pageRecord;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deptListUpdate() {
        String companyId = UserIdThread.get().getCompanyId();
        /*清空旧数据*/
        LambdaQueryWrapper<ProdDept> wrapper = new LambdaQueryWrapper<ProdDept>()
                .eq(ProdDept::getCompanyId,companyId);
        deptMapper.delete(wrapper);
        /*重新拉取部门数据*/
        deptMapper.pull(companyId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void ScheduleUpdateDayDhDeptProd(LocalDateTime time,Integer day) {
        String companyId = UserIdThread.get() == null ? "BF" : UserIdThread.get().getCompanyId();
        /*初始化时间*/
        time = time==null? LocalDate.now().atStartOfDay():time;
        day = day==null||day<1?1:day;
        for (Integer i = day; i > 1; i++) {
            /*循环遍历指定时间段*/
            time = time.minusDays(i);
            /*删除旧数据*/
            generateProdReportMapper.deleteByDate(time,companyId);
            /*获取并写入新数据*/
            generateProdReportMapper.pull(time,companyId);

        }
        /*清除数据*/

    }


    /**
     * 更新月产量
     * year 今天的年份 比如 2025
     * yearAndMonth 今天的年月 比如 202501
     * @return
     */
    @Override
    @Transactional
    @RedisLock(key = "task:Finance.ScheduleUpdateMonthDhDeptProd")
    public ResponseInfo updateMonthProd(String year, String yearAndMonth, String companyId) {
        try{
            // 获取当前日期
            LocalDate today = LocalDate.now();
            int day = today.getDayOfMonth();

            //更新今天和昨天的日报表
            //更新冲裁，工艺，配套日报表数据
            stkAccService.updateForced(2,1);

            //更新数据
            //updateDhDeptProd(companyId, year ,yearAndMonth);
            log.info("更新月产量结束");
            return ResponseInfo.ok();
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceErrorException(e.getMessage());
        }
    }

    @Override
    public Map<String, Object> getDailyProdDetail(String prodStep, String deptName, LocalDateTime date) {
        String companyId = UserIdThread.get().getCompanyId();
        /*分别处理数据*/
        List<DailyReportDetailDto> dtoList = new ArrayList<>();
        int count = 0;
        switch (prodStep){
            case "针车":
                dtoList=stitchMapper.getDailyProdDetail(companyId,deptName,date);
                break;
            case "成型":
                dtoList=lastMapper.getDailyProdDetail(companyId,deptName,date);
                break;
            case "配套":
                count++;
            case "工艺":
                count++;
            case "冲裁":
                count++;
                String processCode = String.format("%02d", count);
                dtoList=cutMapper.getDailyProdDetail(companyId,processCode,date);
                break;
            default:
                break;
        }
        /*封装返回*/
        BigDecimal prodQtySum = dtoList.stream().map(DailyReportDetailDto::getProdQty).reduce(BigDecimal.ZERO, BigDecimal::add);
        Map<String,Object> map = new HashMap(2);
        map.put("dtoList",dtoList);
        map.put("prodQtySum", prodQtySum);
        return map;
    }
    //
    ///**
    // * 更新部门月生产状况产量
    // * @param companyId 公司 默认BF
    // * @param yearYesterday 年 2025
    // * @param yearAndMonthYesterday 年日 202501
    // */
    //public void updateDhDeptProd( String companyId, String yearYesterday ,String yearAndMonthYesterday){
    //
    //    // 1.删除现有月份数据
    //    int count1 = generateProdReportMapper.deleteDhDeptProdStatusByCompanyAndMonth(companyId, yearAndMonthYesterday);
    //    int count2 = generateProdReportMapper.deleteDhDeptProdStatusMByCompanyAndMonth(companyId, yearAndMonthYesterday);
    //    int count3 = generateProdReportMapper.deleteDhDeptProdStatusDByCompanyAndMonth(companyId, yearAndMonthYesterday);
    //
    //    //2.查询 YP_YEAR_MONTH 是否存在今年的数据；存在就不管，不存在就新增今年从1月到12月的数据
    //    int yearCount = generateProdReportMapper.countYpYearMonth(yearYesterday);
    //    if(yearCount == 0){
    //        List<String> monthList = new ArrayList<>();
    //        for (int i = 0; i < 12; i++) {
    //            if(i < 9){
    //                monthList.add(yearYesterday + "0" + (i+1));
    //            }else{
    //                monthList.add(yearYesterday + (i+1));
    //            }
    //        }
    //        generateProdReportMapper.insertYpYearMonthBatch(yearYesterday,monthList);
    //    }
    //
    //    // 3.检查该公司 DhDeptProdStatusM 是否有月份记录
    //    //1》第一次初始化所有
    //    int cnt = generateProdReportMapper.countByCompany(companyId, null);
    //    //2》初始化现有月份数据
    //    int cnt2 = generateProdReportMapper.countByCompany(companyId, yearAndMonthYesterday);
    //
    //    if (cnt == 0 ) {
    //        // 插入 DhDeptProdStatusM 初始数据
    //        generateProdReportMapper.insertInitialData(companyId, null, null);
    //        // 更新各个生产步骤的产量
    //        updateProductionQuantities(companyId,null, null);
    //    } else if(cnt2 == 0){
    //        // 插入 DhDeptProdStatusM 初始数据（现有月份的数据）
    //        generateProdReportMapper.insertInitialData(companyId, yearYesterday, yearAndMonthYesterday);
    //        //2.更新昨天的当月产量
    //        updateProductionQuantities(companyId,yearYesterday, yearAndMonthYesterday);
    //    }else{
    //        //3.更新昨天的当月产量
    //        updateProductionQuantities(companyId,yearYesterday, yearAndMonthYesterday);
    //    }
    //
    //    // 插入日志记录
    //    generateProdReportMapper.insertDhNewExecuteLog("2.1");
    //}
    //
    ///**
    // * 更新不同生产步骤的当月产量
    // * 1.冲裁  2.工艺 3.配套 4针车. 5.成型
    // */
    //private void updateProductionQuantities(String companyId, String year, String yearAndMonth) {
    //    // 一、冲裁 01 （以前用的 PC_CUTTING_DAILY_REPORT 日报表，现在用：PC_CUTTING_COLLECT_DETAIL 收料）
    //    generateProdReportMapper.updateProdQty(companyId, 1, 1,yearAndMonth); //所有部门当月总数量
    //
    //    // 二、工艺/手工 02
    //    generateProdReportMapper.updateProdQty(companyId, 2, 1,yearAndMonth); //所有部门当月总数量
    //
    //    // 三、配套 03
    //    generateProdReportMapper.updateProdQty(companyId, 3, 1,yearAndMonth); //所有部门当月总数量
    //
    //    // 四、针车 PC_STITCH_DETAIL_ATTACH
    //    generateProdReportMapper.updateProdQty(companyId, 4, 1,yearAndMonth); //所有部门当月总数量
    //    generateProdReportMapper.updateProdQty(companyId, 4, 2,yearAndMonth);
    //
    //    //五、成型 PC_LAST_COLLECT_DETAIL（派工）；PC_LAST_COLLECT_DETAIL2（产出）
    //    generateProdReportMapper.updateProdQty(companyId, 5, 1,yearAndMonth); //所有部门当月总数量
    //    generateProdReportMapper.updateProdQty(companyId, 5, 2,yearAndMonth);
    //
    //}


}
